using System;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Microsoft.Expression.Interactivity.Core
{
	public class ChangePropertyAction : TargetedTriggerAction<object>
	{
		public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register("PropertyName", typeof(string), typeof(ChangePropertyAction), null);
		public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(ChangePropertyAction), null);
		public static readonly DependencyProperty DurationProperty = DependencyProperty.Register("Duration", typeof(Duration), typeof(ChangePropertyAction), null);
		public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(bool), typeof(ChangePropertyAction), null);
		public static readonly DependencyProperty EaseProperty = DependencyProperty.Register("Ease", typeof(IEasingFunction), typeof(ChangePropertyAction), null);
		public string PropertyName
		{
			get
			{
				return (string)base.GetValue(ChangePropertyAction.PropertyNameProperty);
			}
			set
			{
				base.SetValue(ChangePropertyAction.PropertyNameProperty, value);
			}
		}
		public object Value
		{
			get
			{
				return base.GetValue(ChangePropertyAction.ValueProperty);
			}
			set
			{
				base.SetValue(ChangePropertyAction.ValueProperty, value);
			}
		}
		public Duration Duration
		{
			get
			{
				return (Duration)base.GetValue(ChangePropertyAction.DurationProperty);
			}
			set
			{
				base.SetValue(ChangePropertyAction.DurationProperty, value);
			}
		}
		public bool Increment
		{
			get
			{
				return (bool)base.GetValue(ChangePropertyAction.IncrementProperty);
			}
			set
			{
				base.SetValue(ChangePropertyAction.IncrementProperty, value);
			}
		}
		public IEasingFunction Ease
		{
			get
			{
				return (IEasingFunction)base.GetValue(ChangePropertyAction.EaseProperty);
			}
			set
			{
				base.SetValue(ChangePropertyAction.EaseProperty, value);
			}
		}
		protected override void Invoke(object parameter)
		{
			if (base.AssociatedObject == null)
			{
				return;
			}
			if (string.IsNullOrEmpty(this.PropertyName))
			{
				return;
			}
			if (base.Target == null)
			{
				return;
			}
			Type type = base.Target.GetType();
			PropertyInfo property = type.GetProperty(this.PropertyName);
			this.ValidateProperty(property);
			object obj = this.Value;
			TypeConverter typeConverter = TypeConverterHelper.GetTypeConverter(property.get_PropertyType());
			Exception ex = null;
			try
			{
				if (this.Value != null)
				{
					if (typeConverter != null && typeConverter.CanConvertFrom(this.Value.GetType()))
					{
						obj = typeConverter.ConvertFrom(this.Value);
					}
					else
					{
						typeConverter = TypeConverterHelper.GetTypeConverter(this.Value.GetType());
						if (typeConverter != null && typeConverter.CanConvertTo(property.get_PropertyType()))
						{
							obj = typeConverter.ConvertTo(this.Value, property.get_PropertyType());
						}
					}
				}
				if (this.Duration.get_HasTimeSpan())
				{
					this.ValidateAnimationPossible(type);
					object currentPropertyValue = ChangePropertyAction.GetCurrentPropertyValue(base.Target, property);
					this.AnimatePropertyChange(property, currentPropertyValue, obj);
				}
				else
				{
					if (this.Increment)
					{
						obj = this.IncrementCurrentValue(property);
					}
					property.SetValue(base.Target, obj, new object[0]);
				}
			}
			catch (FormatException ex2)
			{
				ex = ex2;
			}
			catch (ArgumentException ex3)
			{
				ex = ex3;
			}
			catch (MethodAccessException ex4)
			{
				ex = ex4;
			}
			if (ex != null)
			{
				throw new ArgumentException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionCannotSetValueExceptionMessage, new object[]
				{
					(this.Value != null) ? this.Value.GetType().get_Name() : "null",
					this.PropertyName,
					property.get_PropertyType().get_Name()
				}), ex);
			}
		}
		private void AnimatePropertyChange(PropertyInfo propertyInfo, object fromValue, object newValue)
		{
			Storyboard storyboard = new Storyboard();
			Timeline timeline;
			if (typeof(double).IsAssignableFrom(propertyInfo.get_PropertyType()))
			{
				timeline = this.CreateDoubleAnimation((double)fromValue, (double)newValue);
			}
			else
			{
				if (typeof(Color).IsAssignableFrom(propertyInfo.get_PropertyType()))
				{
					timeline = this.CreateColorAnimation((Color)fromValue, (Color)newValue);
				}
				else
				{
					if (typeof(Point).IsAssignableFrom(propertyInfo.get_PropertyType()))
					{
						timeline = this.CreatePointAnimation((Point)fromValue, (Point)newValue);
					}
					else
					{
						timeline = this.CreateKeyFrameAnimation(fromValue, newValue);
					}
				}
			}
			timeline.set_Duration(this.Duration);
			storyboard.get_Children().Add(timeline);
			Storyboard.SetTarget(storyboard, (DependencyObject)base.Target);
			Storyboard.SetTargetProperty(storyboard, new PropertyPath(propertyInfo.get_Name(), new object[0]));
			storyboard.add_Completed(delegate(object sender, EventArgs e)
			{
				propertyInfo.SetValue(this.Target, newValue, new object[0]);
			});
			storyboard.set_FillBehavior(1);
			storyboard.Begin();
		}
		private static object GetCurrentPropertyValue(object target, PropertyInfo propertyInfo)
		{
			FrameworkElement frameworkElement = target as FrameworkElement;
			target.GetType();
			object obj = propertyInfo.GetValue(target, null);
			if (frameworkElement != null && (propertyInfo.get_Name() == "Width" || propertyInfo.get_Name() == "Height") && double.IsNaN((double)obj))
			{
				if (propertyInfo.get_Name() == "Width")
				{
					obj = frameworkElement.get_ActualWidth();
				}
				else
				{
					obj = frameworkElement.get_ActualHeight();
				}
			}
			return obj;
		}
		private void ValidateAnimationPossible(Type targetType)
		{
			if (this.Increment)
			{
				throw new InvalidOperationException(ExceptionStringTable.ChangePropertyActionCannotIncrementAnimatedPropertyChangeExceptionMessage);
			}
			if (!typeof(DependencyObject).IsAssignableFrom(targetType))
			{
				throw new InvalidOperationException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionCannotAnimateTargetTypeExceptionMessage, new object[]
				{
					targetType.get_Name()
				}));
			}
		}
		private Timeline CreateKeyFrameAnimation(object newValue, object fromValue)
		{
			ObjectAnimationUsingKeyFrames objectAnimationUsingKeyFrames = new ObjectAnimationUsingKeyFrames();
			DiscreteObjectKeyFrame discreteObjectKeyFrame = new DiscreteObjectKeyFrame();
			discreteObjectKeyFrame.set_KeyTime(KeyTime.FromTimeSpan(new TimeSpan(0L)));
			discreteObjectKeyFrame.set_Value(fromValue);
			DiscreteObjectKeyFrame discreteObjectKeyFrame2 = discreteObjectKeyFrame;
			DiscreteObjectKeyFrame discreteObjectKeyFrame3 = new DiscreteObjectKeyFrame();
			discreteObjectKeyFrame3.set_KeyTime(KeyTime.FromTimeSpan(this.Duration.get_TimeSpan()));
			discreteObjectKeyFrame3.set_Value(newValue);
			DiscreteObjectKeyFrame discreteObjectKeyFrame4 = discreteObjectKeyFrame3;
			objectAnimationUsingKeyFrames.get_KeyFrames().Add(discreteObjectKeyFrame2);
			objectAnimationUsingKeyFrames.get_KeyFrames().Add(discreteObjectKeyFrame4);
			return objectAnimationUsingKeyFrames;
		}
		private Timeline CreatePointAnimation(Point fromValue, Point newValue)
		{
			PointAnimation pointAnimation = new PointAnimation();
			pointAnimation.set_From(new Point?(fromValue));
			pointAnimation.set_To(new Point?(newValue));
			pointAnimation.set_EasingFunction(this.Ease);
			return pointAnimation;
		}
		private Timeline CreateColorAnimation(Color fromValue, Color newValue)
		{
			ColorAnimation colorAnimation = new ColorAnimation();
			colorAnimation.set_From(new Color?(fromValue));
			colorAnimation.set_To(new Color?(newValue));
			colorAnimation.set_EasingFunction(this.Ease);
			return colorAnimation;
		}
		private Timeline CreateDoubleAnimation(double fromValue, double newValue)
		{
			DoubleAnimation doubleAnimation = new DoubleAnimation();
			doubleAnimation.set_From(new double?(fromValue));
			doubleAnimation.set_To(new double?(newValue));
			doubleAnimation.set_EasingFunction(this.Ease);
			return doubleAnimation;
		}
		private void ValidateProperty(PropertyInfo propertyInfo)
		{
			if (propertyInfo == null)
			{
				throw new ArgumentException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionCannotFindPropertyNameExceptionMessage, new object[]
				{
					this.PropertyName,
					base.Target.GetType().get_Name()
				}));
			}
			if (!propertyInfo.get_CanWrite())
			{
				throw new ArgumentException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionPropertyIsReadOnlyExceptionMessage, new object[]
				{
					this.PropertyName,
					base.Target.GetType().get_Name()
				}));
			}
		}
		private object IncrementCurrentValue(PropertyInfo propertyInfo)
		{
			if (!propertyInfo.get_CanRead())
			{
				throw new InvalidOperationException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionCannotIncrementWriteOnlyPropertyExceptionMessage, new object[]
				{
					propertyInfo.get_Name()
				}));
			}
			object value = propertyInfo.GetValue(base.Target, null);
			Type propertyType = propertyInfo.get_PropertyType();
			TypeConverter typeConverter = TypeConverterHelper.GetTypeConverter(propertyInfo.get_PropertyType());
			object obj = this.Value;
			if (obj != null && value != null)
			{
				if (typeConverter.CanConvertFrom(obj.GetType()))
				{
					obj = TypeConverterHelper.DoConversionFrom(typeConverter, obj);
				}
				object result;
				if (typeof(double).IsAssignableFrom(propertyType))
				{
					result = (double)value + (double)obj;
				}
				else
				{
					if (typeof(int).IsAssignableFrom(propertyType))
					{
						result = (int)value + (int)obj;
					}
					else
					{
						if (typeof(float).IsAssignableFrom(propertyType))
						{
							result = (float)value + (float)obj;
						}
						else
						{
							if (typeof(string).IsAssignableFrom(propertyType))
							{
								result = (string)value + (string)obj;
							}
							else
							{
								result = ChangePropertyAction.TryAddition(value, obj);
							}
						}
					}
				}
				return result;
			}
			return obj;
		}
		private static object TryAddition(object currentValue, object value)
		{
			Type type = value.GetType();
			Type type2 = currentValue.GetType();
			MethodInfo methodInfo = null;
			object obj = value;
			MethodInfo[] methods = type2.GetMethods();
			for (int i = 0; i < methods.Length; i++)
			{
				MethodInfo methodInfo2 = methods[i];
				if (string.Compare(methodInfo2.get_Name(), "op_Addition", 4) == 0)
				{
					ParameterInfo[] parameters = methodInfo2.GetParameters();
					Type parameterType = parameters[1].get_ParameterType();
					if (parameters[0].get_ParameterType().IsAssignableFrom(type2))
					{
						if (!parameterType.IsAssignableFrom(type))
						{
							TypeConverter typeConverter = TypeConverterHelper.GetTypeConverter(parameterType);
							if (!typeConverter.CanConvertFrom(type))
							{
								goto IL_8F;
							}
							obj = TypeConverterHelper.DoConversionFrom(typeConverter, value);
						}
						if (methodInfo != null)
						{
							throw new ArgumentException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.ChangePropertyActionAmbiguousAdditionOperationExceptionMessage, new object[]
							{
								type2.get_Name()
							}));
						}
						methodInfo = methodInfo2;
					}
				}
				IL_8F:;
			}
			object result;
			if (methodInfo != null)
			{
				result = methodInfo.Invoke(null, new object[]
				{
					currentValue,
					obj
				});
			}
			else
			{
				result = value;
			}
			return result;
		}
	}
}
